package controller;

import game.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.*;
import javax.swing.JOptionPane;
import view.*;

/**
 * <p>The controller for a game of chess.</p>
 * 
 * @author Nicole Waldrum
 * @date January 30, 2010
 * @version 1.0
 * 
 * @author Trevor Bastian
 * @date February 22, 2010
 * @version 2.0
 * 
 * @author Mark Kelly
 * @date February 24, 2010
 * @version 2.0
 * 
 * @author Mark Kelly
 * @date March 8, 2010
 * @version 3.0
 *
 */
public class ChessController implements ActionListener {
	public GameState gameState;
	private ChessView view;
	private Point previousPoint;
	
	/**
	 * <p>Creates a new instance of <tt>ChessController</tt></p>
	 * @param cv a <tt>ChessView</tt>
	 */
	public ChessController(ChessView cv) {
		this.view = cv;
		previousPoint = null;
		gameState = new GameState();
	}

	/**
	 * <p>Returns a {@code String} representation of the {@code ChessBoard}</p>
	 * 
	 * @return a {@code String} representation of the {@code ChessBoard}
	 */
	public String boardString() {
		return gameState.getBoard().toString();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void actionPerformed(ActionEvent event) {		
		String command = event.getActionCommand();
		Object source = event.getSource();
		
		// check buttons
		if (source instanceof BoardButton) {
			BoardButton b = (BoardButton)source;
			boardButtonClicked(b);
		}
		
		// check menus
		else if (command == "Exit"){
			quit();
		}
		else if(command == "Chess"){
			startGame(ClassicChess.class, view);
		}
		else if(command == "Knight's Tour"){
			startGame(KnightTour.class, view);
		}
		else if (command == "8 Queen's Problem"){
			startGame(EightQueens.class, view);
		}
		else if (command == "Help") {
			//ChessGUI.showHelp();
			//JOptionPane.showMessageDialog(null, "Please only enter a letter and a number to move.", "How to Move Pieces", JOptionPane.OK_OPTION);
			view.showHelp(gameState.gameType);
		}
		else {
			JOptionPane pane = new JOptionPane();
			pane.setSize(50, 10);
			JOptionPane.showMessageDialog(pane, "Invalid selection.");
		}
	}
	
	/**
	 * <p>Actions to take after a <tt>BoardButton</tt> is clicked.</p>
	 * @param bb the {@code BoardButton} that was clicked
	 */
	private void boardButtonClicked(BoardButton bb) {
		movePiece(bb);
	}
	
	/**
	 * <p>Always sends the current click and the prior click.</p>
	 * 
	 * @param bb the {@code BoardButton} that was pressed
	 */
	private void movePiece(BoardButton bb) {
		gameState.getGameType().movePiece(previousPoint, bb.getLocation());
		previousPoint = bb.getLocation();
	}
	
	/**
	 * <p>Quit the game</p>
	 */
	private void quit() {
		System.exit(0);
	}

	/**
	 * <p>Starts a game of the specified type.</p>
	 * 
	 * @param <T> they type of game
	 * @param clazz a {@code Class<T>} representing the type of game
	 */
	private <T extends GameType> void startGame(Class<T> clazz, ChessView... view) {
		Constructor<T> constructor = null;
		GameType g = null;
		
		try {
			constructor = clazz.getConstructor(); // retrieve the constructor
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		
		try {
			g = constructor.newInstance(); // invoke the constructor
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		
		gameState = new GameState(g);
		g.setGameState(gameState);
		
		for (ChessView cv : view) {
			gameState.addGameStateListener(cv);
			gameState.addOutcomeListener(cv);
		}
	}
}
